﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using OpenFrameworkCore.Controls;

namespace OpenFrameworkWriter.Controls
{
	/// <summary>
	/// 특정 사각형 범위를 선택할 수 있도록 제공해주는 Control
	/// </summary>
	[TemplatePart(Name = RootElementName, Type = typeof(Panel))]
	public sealed class AreaSelectControl : Control
	{
		private const string RootElementName = "RootElement";

		/// <summary>
		/// 4개의 Line에 대한 스타일 이름
		/// Template이 적용된 경우 사용함
		/// </summary>
		private const string TopLineStyleName = "TopLineStyle";
		private const string BottomLineStyleName = "BottomLineStyle";
		private const string LeftLineStyleName = "LeftLineStyle";
		private const string RightLineStyleName = "RightLineStyle";

		// RootElement
		private Panel RootElement;

		// 라인 변수
		private Line TopLine;
		private Line BottomLine;
		private Line LeftLine;
		private Line RightLine;

		// 시작 좌표
		private Point beginPoint;

		// 끝 좌표
		private Point endPoint;

		/// <summary>
		/// 영역이 선택된 경우 호출되는 이벤트
		/// </summary>
		public event EventHandler<AreaSelectControlEventArgs> AreaSelected;

		/// <summary>
		/// 생성자
		/// </summary>
		public AreaSelectControl()
		{
			DefaultStyleKey = typeof(AreaSelectControl);

			// Line 초기화
			TopLine = new Line();
			BottomLine = new Line();
			LeftLine = new Line();
			RightLine = new Line();

			// Line 감춤
			CollapsedLines();
		}

		/// <summary>
		/// AreaSelect 시작
		/// </summary>
		public void BeginAreaSelecting(Point beginPoint)
		{
			// 시작, 끝 좌표 설정
			this.beginPoint = beginPoint;
			this.endPoint = beginPoint;

			// 라인 그림
			RedrawLines();

			VisibleLines();

			this.CaptureMouse();

			// MouseMove 이벤트 핸들러 설치
			MouseMove += new MouseEventHandler(AreaSelecting);
		}

		/// <summary>
		/// Area 선택
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void AreaSelecting(object sender, MouseEventArgs e)
		{
			// 현재 좌표로 EndPoint 설정
			endPoint = e.GetPosition(this);

			// 라인 그림
			RedrawLines();
		}

		/// <summary>
		/// AreaSelect 중지
		/// </summary>
		public void EndAreaSelecting()
		{
			MouseMove -= new MouseEventHandler(AreaSelecting);

			this.ReleaseMouseCapture();

			CollapsedLines();

			// 이벤트 인자 생성
			AreaSelectControlEventArgs eventArgs = new AreaSelectControlEventArgs();
			eventArgs.BeginPoint = beginPoint;
			eventArgs.EndPoint = endPoint;

			// 선택된 타입이 점인지 그룹인지 체크
			if (beginPoint.Equals(endPoint))
				eventArgs.SelectType = SelectType.Point;
			else
				eventArgs.SelectType = SelectType.Area;

			// 좌표 초기화
			this.beginPoint = new Point(0, 0);
			this.endPoint = new Point(0, 0);

			// 라인 그림
			RedrawLines();

			// AreaSelected 이벤트 발생
			if (AreaSelected != null)
				AreaSelected(this, eventArgs);
		}

		/// <summary>
		/// Template이 적용된 경우 호출되는 메서드
		/// </summary>
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			RootElement = (Panel)GetTemplateChild(RootElementName);
			if (RootElement == null)
				throw new TemplatePartNotFoundException("RootElement를 찾을 수 없습니다.");

			RootElement.Children.Add(TopLine);
			RootElement.Children.Add(BottomLine);
			RootElement.Children.Add(LeftLine);
			RootElement.Children.Add(RightLine);

			
			Style topLineStyle = RootElement.Resources[TopLineStyleName] as Style;
			if (topLineStyle == null)
				throw new TemplatePartNotFoundException("TopLineStyle을 찾을 수 없습니다.");

			TopLine.Style = topLineStyle;


			Style bottomLineStyle = RootElement.Resources[BottomLineStyleName] as Style;
			if (bottomLineStyle == null)
				throw new TemplatePartNotFoundException("BottomLineStyle을 찾을 수 없습니다.");

			BottomLine.Style = bottomLineStyle;


			Style leftLineStyle = RootElement.Resources[LeftLineStyleName] as Style;
			if (leftLineStyle == null)
				throw new TemplatePartNotFoundException("LeftLineStyle을 찾을 수 없습니다.");

			LeftLine.Style = leftLineStyle;


			Style rightLineStyle = RootElement.Resources[RightLineStyleName] as Style;
			if (rightLineStyle == null)
				throw new TemplatePartNotFoundException("RightLineStyle을 찾을 수 없습니다.");

			RightLine .Style= rightLineStyle;
		}

		/// <summary>
		/// Line 감춤
		/// </summary>
		private void CollapsedLines()
		{
			TopLine.Visibility = Visibility.Collapsed;
			BottomLine.Visibility = Visibility.Collapsed;
			LeftLine.Visibility = Visibility.Collapsed;
			RightLine.Visibility = Visibility.Collapsed;
		}

		/// <summary>
		/// Line 보임
		/// </summary>
		private void VisibleLines()
		{
			TopLine.Visibility = Visibility.Visible;
			BottomLine.Visibility = Visibility.Visible;
			LeftLine.Visibility = Visibility.Visible;
			RightLine.Visibility = Visibility.Visible;
		}

		/// <summary>
		/// Line 다시 그림
		/// </summary>
		private void RedrawLines()
		{
			// Top Line
			TopLine.X1 = beginPoint.X;
			TopLine.Y1 = beginPoint.Y;
			TopLine.X2 = endPoint.X;
			TopLine.Y2 = beginPoint.Y;

			// Bottom Line
			BottomLine.X1 = beginPoint.X;
			BottomLine.Y1 = endPoint.Y;
			BottomLine.X2 = endPoint.X;
			BottomLine.Y2 = endPoint.Y;

			// Left Line
			LeftLine.X1 = beginPoint.X;
			LeftLine.Y1 = beginPoint.Y;
			LeftLine.X2 = beginPoint.X;
			LeftLine.Y2 = endPoint.Y;

			// Right Line
			RightLine.X1 = endPoint.X;
			RightLine.Y1 = beginPoint.Y;
			RightLine.X2 = endPoint.X;
			RightLine.Y2 = endPoint.Y;
		}
	}
}
